import path from 'node:path';
import fs from 'fs-extra';
import sharp from 'sharp';
import { NextResponse } from 'next/server';
import { AppStoreSystemConfig } from 'src/lib/AppStoreSystemConfig';
import { prisma } from 'src/lib/prisma';
import { loadSession } from 'src/lib/session';
import type { Params } from './types';
import type { NextRequest } from 'next/server';

const appStorageSystemConfig = new AppStoreSystemConfig<{ basePath: string }>();

// 超时响应时间
export const maxDuration = 60;

/**
 * 响应式图片服务：动态图片处理
 * @param req - 请求对象
 */
export async function GET(req: NextRequest, { params }: { params: Promise<{ name: string[] }> }) {
  try {
    const { name } = await params; // name 对应 数据库 Image 表的 publicUrl
    const { searchParams } = new URL(req.url);

    const fileName = name[name.length - 1]; // 文件名
    const originFormat = path.extname(fileName).toLowerCase().slice(1); // 扩展名去掉点

    // 获取图片处理参数
    const _width = searchParams.get('width') || searchParams.get('w');
    const _height = searchParams.get('height') || searchParams.get('h');
    const _quality = searchParams.get('quality') || searchParams.get('q');
    const _format = searchParams.get('format') || searchParams.get('f');
    const _fit = searchParams.get('fit');
    const _blur = searchParams.get('blur');

    // 赋值
    const width: Params['width'] = _width ? Number(_width) : undefined;
    const height: Params['height'] = _height ? Number(_height) : undefined;
    const fit: Params['fit'] = (_fit as keyof sharp.FitEnum) ?? undefined;
    const format: Params['format'] = _format ? _format.toLowerCase() : originFormat; // 默认使用原始格式
    const nQ = Number(_quality);
    const nB = Number(_blur);
    let quality: Params['quality'] = !Number.isNaN(nQ) ? nQ : undefined;
    let blur: Params['blur'] = !Number.isNaN(nB) ? nB : undefined;

    // 限制 quality 取值范围: 1-100
    quality = quality ? Math.max(1, Math.min(quality, 100)) : undefined;
    // 限制 blur 取值范围: 1-100
    blur = blur ? Math.max(1, Math.min(blur, 100)) : undefined;

    // 读取原始图片
    const publicUrl = '/' + name.join('/'); // 将 restful 参数拼接成 publicUrl
    const image = await prisma.image.findUnique({
      where: {
        publicUrl,
      },
    });
    if (!image?.storagePath) {
      return new NextResponse('Image not found', { status: 404 });
    }
    if (!image.isPublic) {
      const session = await loadSession();
      if (session.userId !== image.userId) {
        return new NextResponse('Image is not public', { status: 403 });
      }
    }
    const storageSystemId = image.storageSystemId;
    const config = await appStorageSystemConfig.getConfig<{ basePath: string }>(storageSystemId);
    if (!config) {
      throw new Error('storage system config not found');
    }

    // Sharp 实例
    let processedImage: sharp.Sharp | undefined;

    // --- 读取 ---
    // 读取私有存储服务图片：local
    if (config.type === 'local') {
      const basePath = AppStoreSystemConfig.parseSystemPath(config.config.basePath);
      const storagePath = image.storagePath;
      const filePath = path.join(basePath, storagePath);
      if (!fs.existsSync(filePath)) {
        throw new Error('file not found');
      }
      const imageBuffer = await fs.readFile(filePath);
      processedImage = sharp(imageBuffer); // 如果不是图片，会抛出异常
    }

    // TODO: 读取云存储服务图片：oss, kodo 等

    if (!processedImage) {
      throw new Error('Image processing failed: image not found');
    }

    // --- Sharp 实例处理 ---
    // Resize
    processedImage = processedImage.resize({
      width,
      height,
      fit,
    });

    // Blur
    if (blur) {
      processedImage = processedImage.blur(blur);
    }

    // 设置输出格式和质量
    let contentType = 'image/png';
    switch (format) {
      case 'jpeg':
      case 'jpg':
        processedImage = processedImage.jpeg({ quality });
        contentType = 'image/jpeg';
        break;
      case 'webp':
        processedImage = processedImage.webp({ quality });
        contentType = 'image/webp';
        break;
      case 'avif':
        processedImage = processedImage.avif({ quality });
        contentType = 'image/avif';
        break;
      case 'gif':
        processedImage = processedImage.gif();
        contentType = 'image/gif';
        break;
      case 'tiff':
        processedImage = processedImage.tiff({ quality });
        contentType = 'image/tiff';
        break;
      case 'png':
      default:
        processedImage = processedImage.png({ quality });
        contentType = 'image/png';
        break;
    }

    // 输出处理后的图片
    const outputBuffer = await processedImage.toBuffer();

    // 返回图片
    // Cache:
    // - public: 允许不仅是浏览器缓存，还包括 CDN、代理服务器等中间缓存服务器缓存该资源
    // - max-age: 缓存时间，单位为秒
    // - immutable: 该资源不会改变，即使服务器端资源发生了变化，浏览器也不会重新请求该资源
    return new NextResponse(outputBuffer, {
      headers: {
        'Content-Type': contentType,
        'Cache-Control': 'public, max-age=31536000, immutable',
        'Content-Length': outputBuffer.length.toString(),
        'Accept-Ranges': 'bytes',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, OPTIONS',
      },
    });
  } catch (error) {
    return new NextResponse(`Image processing failed: ${(error as Error).message ?? 'unknown'}`, {
      status: 500,
    });
  }
}
